home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / bccapp.zip / BATCH.C < prev    next >
C/C++ Source or Header  |  1991-09-15  |  11KB  |  504 lines

  1. /*
  2.  *
  3.  * Edit Batch entries.  Uses EDIT object as a parent Class
  4.  *
  5.  * (C) 1990 Vision Software
  6.  *
  7.  * $Id: batch.c 1.2003 91/05/06 14:23:40 pcalvin beta $
  8.  *
  9.  * Comments:
  10.  *
  11.  * This class allows the user to Add/Edit and Delete structures without
  12.  * the usual headaches.  This class is a collection of various others
  13.  * EDIT handles the Field I/O.  DATABASE handles the Record I/O.  Not
  14.  * much to do but sit back and take the credit..
  15.  *
  16.  * Bugs:
  17.  *
  18.  *    None documented
  19.  */
  20. #include <ctype.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <conio.h>
  25. #include <io.h>
  26.  
  27. #include <stdhdr.h>
  28.  
  29. #include <adl.h>
  30. #include <menu.h>
  31. #include <dbase.h>
  32. #include <edit.h>
  33. #include <batch.h>
  34.  
  35. #include "lowlevel.h"
  36.  
  37. /*
  38.  *    Strings used for the various run-time operations
  39.  */
  40. STATIC SZ szAskCreate = "Would you like to create this record?";
  41. STATIC SZ szHlpCreate = "Press \"Y\" to create, \"N\" to abandon";
  42. STATIC SZ szAskSave = "Would you like to save the changes?";
  43. STATIC SZ szHlpSave = "Press \"Y\" to save this record, \"N\" to abandon changes";
  44. STATIC SZ szAskDelete = "Delete this record, Are you sure?";
  45. STATIC SZ szHlpDelete = "Press \"Y\" to delete record, \"N\" to abort";
  46. STATIC SZ szHlpIndex = "Select key for record ordering";
  47.  
  48. INLINE VOID BATCH::PrepRecForRead()
  49.     {
  50.     if (pfnRead != Nil)
  51.         pfnRead(pdtb->PdbQuery());
  52.     }
  53.  
  54. INLINE VOID BATCH::PrepRecForWrite()
  55.     {
  56.     if (pfnWrite != Nil)
  57.         pfnWrite(pdtb->PdbQuery());
  58.     }
  59.         
  60. /*
  61.  * Must open the DATABASE ourselves.  No problem
  62.  */
  63. BATCH::BATCH(DBASE *pdb,CCH cchRecord,SZ szFileName,SZ sz,FNPDB pfnR,FNPDB pfnW) : EDIT(fTrue,sz)
  64.     {
  65.     pdtb = new DATABASE(pdb,cchRecord,szFileName,fTrue);
  66.     fDeleteDatabase = fTrue;
  67.     fCreateRecord = fFalse;
  68.     pfnRead = pfnR;
  69.     pfnWrite = pfnW;
  70.     cmiMac = cmiNil;
  71.     pmiCurrent = pmiNil;
  72.     }
  73.     
  74. /*
  75.  *    Database is already created.  It will remain open after BATCH
  76.  */
  77. BATCH::BATCH(DATABASE &rdtbOriginal,SZ sz,FNPDB pfnR,FNPDB pfnW) : EDIT(fTrue,sz)
  78.     {
  79.     pdtb = &rdtbOriginal;
  80.     fDeleteDatabase = fFalse;
  81.     fCreateRecord = fFalse;
  82.     pfnRead = pfnR;
  83.     pfnWrite = pfnW;
  84.     cmiMac = cmiNil;
  85.     pmiCurrent = pmiNil;
  86.     }
  87.  
  88. /*
  89.  *    Close the DATABASE if it was created
  90.  */
  91. BATCH::~BATCH()
  92.     {
  93.     if (fDeleteDatabase)
  94.         delete pdtb;
  95.     }
  96.  
  97. /*
  98.  *    Initializes the read.  Simply rewinds the DATABASE and calls
  99.  *    EDIT.
  100.  */
  101. VOID BATCH::Read()
  102.     {
  103.     if (cmiMac > cmiNil)
  104.         Verify(FSelectCmi(cmiNil));
  105.     else
  106.         fCreateRecord = !pdtb->FFirst();
  107.  
  108.     EDIT::Read();
  109.     }
  110.     
  111. /*
  112.  *    Creates a field() that may be used to change the active
  113.  *    index file within an edit..
  114.  */
  115. VOID BATCH::IndexSelector(ROW row,COL col,SZ szMsg,CENT cent,PENT pent,CENT centDefault)
  116.     {
  117.     Assert(centDefault < cent);
  118.     Assert(pent != pentNil);
  119.  
  120.     CCH cch = CchFromCentPent(cent,pent);
  121.     
  122.     Field(row,col,szMsg,szSelector,'X',cch,szHlpIndex,pent[centDefault].sz);
  123.     
  124.     centIndex = cent;
  125.     pentIndex = pent;
  126.     pedIndex = PedQuery();   
  127.     
  128.     pedIndex->Adjust(BATCH::FSelect,this,fFalse);
  129.     }
  130.     
  131. /*
  132.  * Sets up an index field.
  133.  */
  134. BOOL BATCH::FCreateIndex(SZ szIndex,CID cid,PED ped)
  135.     {
  136.     AssertSz(cmiMac < cmiOpenMax,"Too many index files");
  137.  
  138.     CMI cmi = cmiMac++;
  139.     SZ sz = pdtb->SzIndex(cid);
  140.     CCH cch = pdtb->CchIndex(cid);
  141.     
  142.     /*
  143.      *    Initialize index record, if there is a default string, copy that
  144.      *    into the index address.
  145.      */
  146.     pmiCurrent = &rgmiActive[cmi]; 
  147.     
  148.     pmiCurrent->cid = cid;
  149.     pmiCurrent->szIndex = szIndex;
  150.     pmiCurrent->sz = sz;
  151.     pmiCurrent->cch = cch;
  152.     pmiCurrent->row =    ped->RowEdit() - 2;
  153.     pmiCurrent->col = ped->ColLeft() - 1;
  154.     
  155.     strncpy(pmiCurrent->szIndex,sz,cch);
  156.  
  157.     /*
  158.      *    And select this as the current index.
  159.      */
  160.     return (FSelectCmi(cmiNil));
  161.     }
  162.  
  163. /*
  164.  *    Hooks up an index field.  CID must be valid or program will ASSERT
  165.  */
  166. VOID BATCH::Index(ROW row,COL col,CID cid,SZ szMessage,CHAR ch,SZ szHelp,SZ szDflt)
  167.     {
  168.     CCH cch = pdtb->CchIndex(cid);
  169.     SZ sz = pdtb->SzIndex(cid);
  170.     SZ szIndex = new CHAR[cch];
  171.     SZ szDefault = (szDflt == szNil) ? szIndex : szDflt;
  172.     
  173.     Field(row,col,szMessage,szIndex,ch,cch,szHelp,szDefault);
  174.  
  175.     PED ped = PedQuery();
  176.     ped->Adjust(BATCH::FChange,this,fFalse);
  177.     
  178.     if (szDefault != szIndex)
  179.         strncpy(sz,szDefault,cch);
  180.     
  181.     Verify(FCreateIndex(szIndex,cid,ped));
  182.     }
  183.     
  184. /*
  185.  * Sets up the index field for this batch
  186.  */
  187. VOID BATCH::Index(ROW row,COL col,SZ szFile,SZ szMessage,SZ sz,CHAR ch,CCH cch,SZ szHelp,SZ szDflt)
  188.     {
  189.     SZ szIndex = new CHAR[cch];
  190.     SZ szDefault = (szDflt == szNil) ? szIndex : szDflt;
  191.     
  192.     Field(row,col,szMessage,szIndex,ch,cch,szHelp,szDefault);
  193.  
  194.     PED ped = PedQuery();
  195.     ped->Adjust(BATCH::FChange,this,fFalse);
  196.     
  197.     if (szDefault != szIndex)
  198.         strncpy(sz,szDefault,cch);
  199.     
  200.     Verify(FCreateIndex(szIndex,pdtb->CidIndexOn(szFile,sz,cch),ped));
  201.     }
  202.  
  203. /*
  204.  *    Copies all indexes to their temporary storage areas..
  205.  */
  206. VOID BATCH::SaveIndexes()
  207.     {
  208.     for (CMI cmi = cmiNil; cmi < cmiMac; cmi++)
  209.         {
  210.         strncpy(rgmiActive[cmi].szIndex,rgmiActive[cmi].sz,rgmiActive[cmi].cch);
  211.         }
  212.     }    
  213.  
  214. /*
  215.  *    Copies all indexes back from the temporary storage area..
  216.  */
  217. VOID BATCH::RestoreIndexes()
  218.     {
  219.     for (CMI cmi = cmiNil; cmi < cmiMac; cmi++)
  220.         {
  221.         strncpy(rgmiActive[cmi].sz,rgmiActive[cmi].szIndex,rgmiActive[cmi].cch);
  222.         }
  223.     } 
  224.     
  225. /* 
  226.  *    Selects new index file.
  227.  */
  228. BOOL BATCH::FSelectCmi(CMI cmi)
  229.     {
  230.     BOOL fValid = fFalse;
  231.         
  232.     if (cmi < cmiMac)
  233.         {
  234.         pmiCurrent = &rgmiActive[cmi];
  235.         
  236.         Verify(pdtb->FIndexTo(pmiCurrent->cid));
  237.         
  238.         /*
  239.          *    If no records are available, clear the fields..
  240.          */
  241.          if (pdtb->FFirst())
  242.              {
  243.              fCreateRecord = fFalse;
  244.              PrepRecForRead();
  245.              }
  246.         else
  247.             {
  248.             fCreateRecord = fTrue;
  249.             ClearFields();
  250.             }
  251.             
  252.         strcpy(szSelector,pentIndex[cmi].sz);
  253.         SaveIndexes();
  254.         RedrawFields();
  255.         fValid = fTrue;
  256.         }
  257.  
  258.     return (fValid);
  259.     }
  260. /*
  261.  * If the current record was modified, AND the user wants it saved,
  262.  * do so, then clear the changed flags
  263.  */
  264. VOID BATCH::MaybeSaveCurrent()
  265.     {
  266.     if (FModified())
  267.         {
  268.         /*
  269.          * The field has been modified, must check if the record needs to be created
  270.          *    as well as saved..
  271.          */
  272.         if (fCreateRecord)
  273.             {
  274.             fCreateRecord = fFalse;
  275.             
  276.             if (FAskSz(szAskCreate,szHlpCreate))
  277.                 {
  278.                 RestoreIndexes();
  279.                 PrepRecForWrite();    
  280.                 Verify(pdtb->FCreate());
  281.                 Verify(pdtb->FSave());
  282.                 }
  283.             else
  284.                 {
  285.                 ClearFields();
  286.                 }
  287.             }
  288.         else if (FAskSz(szAskSave,szHlpSave))
  289.             {
  290.             PrepRecForWrite();    
  291.             Verify(pdtb->FSave());
  292.             }
  293.         }
  294.  
  295.     /*
  296.      * Force "Unchanged" status.
  297.      */
  298.     ForceNoChanges();
  299.     }
  300.  
  301. /*
  302.  * Asks if should Exit, continue or whatever
  303.  */
  304. BOOL BATCH::FExit(void)
  305.     {
  306.     /*
  307.      * Save if needed..
  308.      */
  309.     MaybeSaveCurrent();
  310.     /*
  311.      * Normal exit procedure
  312.      */
  313.     return (EDIT::FExit());
  314.     }
  315.  
  316. /*
  317.  *    Some new functionality added to our EDIT keys.
  318.  *
  319.  *    PgUp:    Next record
  320.  *    PgDn: Previous record
  321.  *    Home: First record
  322.  *    End: Last record
  323.  *    Del: Delete current record
  324.  * Ins: Create record (Useful if creating duplicate key)
  325.  */
  326. BOOL BATCH::FHandleCd(CD cd)
  327.     {
  328.     BOOL fContinue = fTrue;
  329.  
  330.     switch (cd)
  331.         {
  332.     case cdInsert:
  333.         if (pmiCurrent->szIndex[0] != chNil && FAskSz(szAskCreate,szHlpCreate))
  334.             {
  335.             RestoreIndexes();
  336.             PrepRecForWrite();    
  337.             Verify(pdtb->FCreate());
  338.             ClearFields();
  339.             Rewind();
  340.             SaveIndexes();
  341.             RedrawFields();
  342.             Verify(pdtb->FSave());
  343.             }
  344.         break;
  345.     case cdHome:
  346.         /*
  347.          *    Be sure to save any changes..
  348.          */
  349.         MaybeSaveCurrent();
  350.         
  351.         if (pdtb->FFirst())
  352.             {
  353.             PrepRecForRead();
  354.             SaveIndexes();
  355.             RedrawFields();
  356.             }
  357.         break;
  358.     case cdEnd:
  359.         /*
  360.          *    Be sure to save any changes..
  361.          */
  362.         MaybeSaveCurrent();
  363.         
  364.         if (pdtb->FLast())
  365.             {
  366.             PrepRecForRead();
  367.             SaveIndexes();
  368.             RedrawFields();
  369.             }
  370.         break;
  371.     case cdPageUp:
  372.         /*
  373.          *    Be sure to save any changes..
  374.          */
  375.         MaybeSaveCurrent();
  376.         
  377.         if (pdtb->FPrevious())
  378.             {
  379.             PrepRecForRead();
  380.             SaveIndexes();
  381.             RedrawFields();
  382.             }
  383.         break;
  384.     case cdPageDown:
  385.         /*
  386.          *    Be sure to save any changes..
  387.          */
  388.         MaybeSaveCurrent();
  389.         
  390.         if (pdtb->FNext())
  391.             {
  392.             PrepRecForRead();
  393.             SaveIndexes();
  394.             RedrawFields();
  395.             }
  396.         break;
  397.     case cdDelete:
  398.         if (!fCreateRecord && FAskSz(szAskDelete,szHlpDelete))
  399.             {
  400.             fCreateRecord = !pdtb->FDelete();
  401.             PrepRecForRead();
  402.             Rewind();
  403.             SaveIndexes();
  404.             RedrawFields();
  405.             }
  406.         break;
  407.     default:
  408.         fContinue = EDIT::FHandleCd(cd);
  409.         }
  410.  
  411.     return (fContinue);
  412.     }
  413.  
  414. /*
  415.  * Checks for a change in the current field.  If changes are found
  416.  * Ask if save is wanted and attempt to edit the new Field..
  417.  * Because a non-static member function requires a "this" pointer, we
  418.  * make this a static member and pass the "this" pointer explicitly
  419.  */
  420. BOOL BATCH::FChange(SZ sz,VOID *pv)
  421.     {
  422.     BATCH *pvThis = (BATCH *)pv;
  423.     BOOL fContinue = fTrue;
  424.  
  425.     if (pvThis->pmiCurrent->szIndex == sz)
  426.         {
  427.         /*
  428.          * Save record if needed
  429.          */
  430.         pvThis->MaybeSaveCurrent();
  431.  
  432.         /*
  433.          * If the key is empty, provide a finder.  Otherwise, edit or create
  434.          * that key.
  435.          */
  436.         if (*sz == chNil)
  437.             {
  438.             ROW row = pvThis->wndEdit.RowQuery() + pvThis->pmiCurrent->row;
  439.             COL col = pvThis->wndEdit.ColQuery() + pvThis->pmiCurrent->col;
  440.  
  441.             /*
  442.              * Doesn't make sense to provide a finder, if there is nothing to find
  443.              * If no finder provided, answer with an error.  We cannot have
  444.              * blank keys created..
  445.              */
  446.             if (pvThis->pdtb->FFirst())
  447.                 {
  448.                 VSCROLL vscr(row,col,10,*pvThis->pdtb);
  449.                 HELP help("Use cursor keys to select the desired record");
  450.  
  451.                 /*
  452.                  * Supply finder to pick record, illegal entry if finder is ignored.
  453.                  */
  454.                 if (vscr.CentGet() != centError)
  455.                     {
  456.                     pvThis->PrepRecForRead();
  457.                     pvThis->SaveIndexes();
  458.                     }
  459.                 else
  460.                     {
  461.                     pvThis->ClearFields();
  462.                     fContinue = fFalse;
  463.                     }
  464.                 }
  465.             else
  466.                 {
  467.                 fContinue = fFalse;
  468.                 }
  469.             }
  470.         else if (pvThis->pdtb->FGotoSz(sz,fTrue))
  471.             {
  472.             pvThis->PrepRecForRead();
  473.             pvThis->SaveIndexes();
  474.             }
  475.         else
  476.             {
  477.             pvThis->fCreateRecord = fTrue;
  478.             pvThis->ClearFields();
  479.             }
  480.  
  481.         /*
  482.          * Update display
  483.          */
  484.         pvThis->RedrawFields();
  485.         }
  486.  
  487.     return (fContinue);
  488.     }
  489.     
  490. /*
  491.  *    Index selector.  Used to provide finder if user wants to
  492.  *    change indexes..
  493.  */
  494. BOOL BATCH::FSelect(SZ sz,VOID *pv)
  495.     {
  496.     BATCH *pvThis = (BATCH *)pv;
  497.     ROW row = pvThis->wndEdit.RowQuery() + pvThis->pedIndex->RowEdit() - 2;
  498.     COL col = pvThis->wndEdit.ColQuery() + pvThis->pedIndex->ColLeft() - 1;
  499.     POPUP pop(row,col,pvThis->centIndex,pvThis->pentIndex);
  500.     CENT cent = pop.CentGet();
  501.  
  502.     return ((cent == centError) ? fFalse : pvThis->FSelectCmi(cent));
  503.     }
  504.